﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using MethodWorx.Core.DomainModel;
using MethodWorx.CMS.Services;
using MethodWorx.CMS.Content;
using MethodWorx.CMS.Providers;

namespace MethodWorx.CMS.Plugins
{
    public  class PluginRepository : IPluginRepository
    {
        private PluginService service;
        private static IEnumerable<SafePlugin> loadedPlugins;
        private object syncRoot = new object();
        private IRepositoryRegistry repositories;
        private IUnitOfWorkFactory uowFactory;
        private ICmsDataProvider provider;

        public PluginRepository(ICmsDataProvider provider, IUnitOfWorkFactory uowFactory, IRepositoryRegistry repositories)
        {
            this.repositories = repositories;
            this.uowFactory = uowFactory;
            this.provider = provider;
        }

        public PluginRepository(ICmsDataProvider provider)
            : this(provider, provider.GetUnitOfWorkFactory(), provider.GetRepositoryRegistry())
        {
        }

        public IEnumerable<IPlugin> All()
        {
            lock (syncRoot)
            {
                if (loadedPlugins == null)
                {
                    List<SafePlugin> plugins = new List<SafePlugin>();
                    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        if (assembly.GetCustomAttributes(true).OfType<AssemblyContainsPluginsAttribute>().Any())
                        {
                            //
                            //  ok, scan the types
                            foreach (Type type in assembly.GetTypes())
                            {
                                if (!type.IsAbstract && type.IsClass && typeof(IAutoLoadedPlugin).IsAssignableFrom(type))
                                {
                                    try
                                    {
                                        var plugin = new SafePlugin(type, (IPlugin)Activator.CreateInstance(type));
                                        plugin.SetProvider(this.provider);
                                        plugins.Add(plugin);
                                    }
                                    catch (Exception ex)
                                    {
                                        while (ex.InnerException != null)
                                            ex = ex.InnerException;

                                        //  dont bother adding it,
                                        plugins.Add(new SafePlugin(type, null)
                                            {
                                                Exception = ex
                                            });
                                    }
                                }
                            }
                        }
                    }

                    loadedPlugins = plugins.AsReadOnly();
                }

                return loadedPlugins;
            }
        }
    }
}
